﻿namespace USElections.Model
{
    using System;

    /// <summary>
    /// Data class.
    /// </summary>
    public class Data
    {
        #region Fields
        private static readonly Data instance = new Data();
        private Candidates candidates = new Candidates();
        private Candidates runningCandidates = new Candidates();
        private CalendarItems calendarItems = new CalendarItems();
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes static members of the Data class.
        /// </summary>
        static Data()
        {
        }

        /// <summary>
        /// Prevents a default instance of the Data class from being created.
        /// </summary>
        private Data()
        {
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the Data instance.
        /// </summary>
        public static Data Instance
        {
            get
            {
                return instance;
            }
        }

        /// <summary>
        /// Gets the calendar items.
        /// </summary>
        public CalendarItems CalendarItems
        {
            get
            {
                if (this.calendarItems == null || this.calendarItems.Count == 0)
                {
                    this.PopulateCalendarItems();
                }

                return this.calendarItems;
            }
        }

        /// <summary>
        /// Gets the candidates.
        /// </summary>
        public Candidates Candidates
        {
            get
            {
                if (this.candidates == null || this.candidates.Count == 0)
                {
                    this.PopulateCandidates();
                }

                return this.candidates;
            }
        }

        /// <summary>
        /// Gets the candidates that are still running for office.
        /// </summary>
        public Candidates RunningCandidates
        {
            get
            {
                if (this.candidates == null || this.candidates.Count == 0)
                {
                    this.PopulateCandidates();
                }

                if (this.runningCandidates.Count == 0)
                {
                    foreach (Candidate candidate in this.candidates)
                    {
                        if (candidate.Running)
                        {
                            this.runningCandidates.Add(candidate);
                        }
                    }
                }

                return this.runningCandidates;
            }
        }
        #endregion

        #region Private methods
        private void PopulateCandidates()
        {
            this.AddCandidate(new Candidate() { Id = 01, FullName = "Barack Obama", Party = Candidate.Parties.Democratic, ImageUri = "/Images/Icons/obama.jpg", TwitterAccount = "BarackObama", TwitterId = 813286 });
            this.AddCandidate(new Candidate() { Id = 02, Running = false, FullName = "Randall Terry", Party = Candidate.Parties.Democratic, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });

            this.AddCandidate(new Candidate() { Id = 03, Running = false, FullName = "Michele Bachmann", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/bachmann.jpg", TwitterAccount = "TeamBachmann", TwitterId = 16446177 });
            this.AddCandidate(new Candidate() { Id = 04, Running = false, FullName = "Herman Cain", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/cain.jpg", TwitterAccount = "THEHermanCain", TwitterId = 28587919 });
            this.AddCandidate(new Candidate() { Id = 05, Running = false, FullName = "Newt Gingrich", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/gingrich.jpg", TwitterAccount = "Newt2012HQ", TwitterId = 257193354 });
            this.AddCandidate(new Candidate() { Id = 06, Running = false, FullName = "Jon Huntsman, Jr", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/huntsman.jpg", TwitterAccount = "Jon2012HQ", TwitterId = 320406917 });
            this.AddCandidate(new Candidate() { Id = 08, Running = false, FullName = "Ron Paul", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/paul.jpg", TwitterAccount = "RepRonPaul", TwitterId = 76966145 });
            this.AddCandidate(new Candidate() { Id = 09, Running = false, FullName = "Rick Perry", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/perry.jpg", TwitterAccount = "TeamRickPerry", TwitterId = 19084128 });
            this.AddCandidate(new Candidate() { Id = 10, FullName = "Mitt Romney", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/romney.jpg", TwitterAccount = "MittRomney", TwitterId = 50055701 });
            this.AddCandidate(new Candidate() { Id = 11, Running = false, FullName = "Rick Santorum", Party = Candidate.Parties.Republican, ImageUri = "/Images/Icons/santorum.jpg", TwitterAccount = "RickSantorum", TwitterId = 58379000 });

            this.AddCandidate(new Candidate() { Id = 12, FullName = "Kent Mesplay", Party = Candidate.Parties.Green, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });

            this.AddCandidate(new Candidate() { Id = 07, FullName = "Gary Johnson", Party = Candidate.Parties.Libertarian, ImageUri = string.Empty, TwitterAccount = "GovGaryJohnson", TwitterId = 95713333 });
            this.AddCandidate(new Candidate() { Id = 13, FullName = "R. Lee Wrights", Party = Candidate.Parties.Libertarian, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });

            this.AddCandidate(new Candidate() { Id = 14, FullName = "Jack Fellure", Party = Candidate.Parties.Prohibition, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });
            this.AddCandidate(new Candidate() { Id = 15, FullName = "James Hedges", Party = Candidate.Parties.Prohibition, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });

            this.AddCandidate(new Candidate() { Id = 16, FullName = "Stewart Alexander", Party = Candidate.Parties.Socialist, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });

            this.AddCandidate(new Candidate() { Id = 17, FullName = "Roseanne Barr", Party = Candidate.Parties.Independent, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });
            this.AddCandidate(new Candidate() { Id = 18, FullName = "Robert Burck", Party = Candidate.Parties.Independent, ImageUri = string.Empty, TwitterAccount = string.Empty, TwitterId = -1 });
            this.AddCandidate(new Candidate() { Id = 19, FullName = "Joe Schriner", Party = Candidate.Parties.Independent, ImageUri = string.Empty, TwitterAccount = "joeschriner", TwitterId = 14845947 });
        }

        private void AddCandidate(Candidate candidate)
        {
            this.candidates.Add(candidate);
        }

        private void PopulateCalendarItems()
        {
            /* january */
            this.Add("USE_001", new DateTime(2012, 01, 03, 10, 0, 0), "Iowa caucuses", "-");
            this.Add("USE_002", new DateTime(2012, 01, 07, 21, 0, 0), "GOP debate", "on ABC in NH Sponsor: ABC News and WMUR");
            this.Add("USE_003", new DateTime(2012, 01, 08, 9, 0, 0), "GOP debate", "on NBC in NH, Sponsor: NBC News, Facebook and the Union Leader");
            this.Add("USE_004", new DateTime(2012, 01, 10, 10, 0, 0), "New Hampshire primary", "-");
            this.Add("USE_005", new DateTime(2012, 01, 21, 10, 0, 0), "South Carolina primary", "-");

            this.Add("USE_013", new DateTime(2012, 01, 26, 10, 0, 0), "GOP debate", "On CNN in FL");

            this.Add("USE_006", new DateTime(2012, 01, 31, 10, 0, 0), "Florida primary", "-");
            this.Add("USE_039", new DateTime(2012, 01, 31, 10, 0, 0), "Oregon CD-1 Special Election", "-");

            /* february */
            this.Add("USE_007", new DateTime(2012, 02, 04, 10, 0, 0), "Nevada caucuses", "-");
            this.Add("USE_040", new DateTime(2012, 02, 04, 10, 0, 0), "Maine caucuses", "-");

            this.Add("USE_008", new DateTime(2012, 02, 07, 10, 0, 0), "Colorado caucuses", "-");
            this.Add("USE_041", new DateTime(2012, 02, 07, 10, 0, 0), "Minnesota caucuses", "-");
            this.Add("USE_042", new DateTime(2012, 02, 07, 10, 0, 0), "Missouri primary", "-");

            this.Add("USE_009", new DateTime(2012, 02, 22, 10, 0, 0), "GOP debate", "on CNN in AZ");

            this.Add("USE_010", new DateTime(2012, 02, 28, 10, 0, 0), "Arizona primary", "-");
            this.Add("USE_011", new DateTime(2012, 02, 28, 10, 0, 0), "Michigan primary", "-");

            /* march */
            this.Add("USE_014", new DateTime(2012, 03, 03, 10, 0, 0), "Washington (state) GOP caucuses", "-");
            this.Add("USE_015", new DateTime(2012, 03, 05, 10, 0, 0), "GOP debate", "on NBC in CA");

            this.Add("USE_057", new DateTime(2012, 03, 06, 10, 0, 0), "Super Tuesday", "-");

            this.Add("USE_016", new DateTime(2012, 03, 06, 10, 0, 0), "Alaska caucuses", "-");
            this.Add("USE_017", new DateTime(2012, 03, 06, 10, 0, 0), "Georgia primary", "-");
            this.Add("USE_018", new DateTime(2012, 03, 06, 10, 0, 0), "Idaho caucuses", "-");
            this.Add("USE_019", new DateTime(2012, 03, 06, 10, 0, 0), "Massachusetts primary", "-");
            this.Add("USE_021", new DateTime(2012, 03, 06, 10, 0, 0), "Ohio primary", "-");
            this.Add("USE_022", new DateTime(2012, 03, 06, 10, 0, 0), "Oklahoma primary", "-");
            this.Add("USE_023", new DateTime(2012, 03, 06, 10, 0, 0), "Tennessee primary", "-");
            this.Add("USE_024", new DateTime(2012, 03, 06, 10, 0, 0), "Vermont primary", "-");
            this.Add("USE_025", new DateTime(2012, 03, 06, 10, 0, 0), "Virginia primary", "-");
            this.Add("USE_026", new DateTime(2012, 03, 06, 10, 0, 0), "Wyoming caucuses", "-");
            this.Add("USE_038", new DateTime(2012, 03, 06, 10, 0, 0), "North Dakota caucuses", "-");

            this.Add("USE_027", new DateTime(2012, 03, 10, 10, 0, 0), "Kansas caucuses", "-");
            this.Add("USE_043", new DateTime(2012, 03, 10, 10, 0, 0), "US Virgin Islands caucuses", "-");

            this.Add("USE_029", new DateTime(2012, 03, 13, 10, 0, 0), "Alabama primary", "-");
            this.Add("USE_030", new DateTime(2012, 03, 13, 10, 0, 0), "Hawaii caucuses", "-");
            this.Add("USE_031", new DateTime(2012, 03, 13, 10, 0, 0), "Mississippi primary", "-");

            this.Add("USE_033", new DateTime(2012, 03, 17, 10, 0, 0), "Missouri caucuses", "-");

            this.Add("USE_034", new DateTime(2012, 03, 18, 10, 0, 0), "Puerto Rico primary", "-");

            this.Add("USE_035", new DateTime(2012, 03, 19, 10, 0, 0), "GOP debate", "on PBS in OR");

            this.Add("USE_036", new DateTime(2012, 03, 20, 10, 0, 0), "Illinois primary", "-");

            this.Add("USE_037", new DateTime(2012, 03, 24, 10, 0, 0), "Louisiana primary", "-");

            /* april */
            this.Add("USE_052", new DateTime(2012, 04, 03, 10, 0, 0), "District of Columbia primary", "-");
            this.Add("USE_053", new DateTime(2012, 04, 03, 10, 0, 0), "Maryland primary", "-");
            this.Add("USE_054", new DateTime(2012, 04, 03, 10, 0, 0), "Mississippi primary", "-");
            this.Add("USE_055", new DateTime(2012, 04, 03, 10, 0, 0), "Texas primary", "-");
            this.Add("USE_056", new DateTime(2012, 04, 03, 10, 0, 0), "Wisconsin primary", "-");

            this.Add("USE_044", new DateTime(2012, 04, 18, 10, 0, 0), new DateTime(2012, 04, 21, 10, 0, 0), "Constitution party Presidential Nominating Conv.", "-");

            this.Add("USE_045", new DateTime(2012, 04, 21, 10, 0, 0), "Utah Republican state nominating conv.", "-");

            this.Add("USE_046", new DateTime(2012, 04, 24, 10, 0, 0), "Alabama primary", "-");
            this.Add("USE_047", new DateTime(2012, 04, 24, 10, 0, 0), "Connecticut primary", "-");
            this.Add("USE_048", new DateTime(2012, 04, 24, 10, 0, 0), "Delaware primary", "-");
            this.Add("USE_049", new DateTime(2012, 04, 24, 10, 0, 0), "New York primary", "-");
            this.Add("USE_050", new DateTime(2012, 04, 24, 10, 0, 0), "Pennsylvania primary", "-");
            this.Add("USE_051", new DateTime(2012, 04, 24, 10, 0, 0), "Rhode Island primary", "-");

            /* may */
            this.Add("USE_058", new DateTime(2012, 05, 08, 10, 0, 0), "Indiana primary", "-");
            this.Add("USE_059", new DateTime(2012, 05, 08, 10, 0, 0), "North Carolina primary", "-");
            this.Add("USE_060", new DateTime(2012, 05, 08, 10, 0, 0), "West Virginia primary", "-");

            this.Add("USE_061", new DateTime(2012, 05, 15, 10, 0, 0), "Nebraska primary", "-");
            this.Add("USE_062", new DateTime(2012, 05, 15, 10, 0, 0), "Oregon primary", "-");

            this.Add("USE_063", new DateTime(2012, 05, 22, 10, 0, 0), "Arkansas primary", "-");
            this.Add("USE_064", new DateTime(2012, 05, 22, 10, 0, 0), "Kentucky primary", "-");

            this.Add("USE_065", new DateTime(2012, 05, 29, 10, 0, 0), "Texas primary", "-");

            /* june */
            this.Add("USE_066", new DateTime(2012, 06, 05, 10, 0, 0), "California primary", "-");
            this.Add("USE_067", new DateTime(2012, 06, 05, 10, 0, 0), "Montana primary", "-");
            this.Add("USE_068", new DateTime(2012, 06, 05, 10, 0, 0), "New Jersey primary", "-");
            this.Add("USE_069", new DateTime(2012, 06, 05, 10, 0, 0), "New Mexico primary", "-");
            this.Add("USE_070", new DateTime(2012, 06, 05, 10, 0, 0), "South Dakota primary", "-");

            this.Add("USE_071", new DateTime(2012, 06, 26, 10, 0, 0), "Utah primary", "-");

            /* 72 */
            
            /* november */
            this.Add("USE_012", new DateTime(2012, 11, 06, 10, 0, 0), "Election day", "Election day 2012");
        }

        private void Add(string id, DateTime start, string subject, string details)
        {
            this.Add(id, start, start, subject, details);
        }

        private void Add(string id, DateTime start, DateTime end, string subject, string details)
        {
            foreach (var item in this.calendarItems)
            {
                if (string.Compare(id, item.Id, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    throw new ArgumentException("Id is already used.");
                }
            }

            this.calendarItems.Add(new CalendarItem()
            {
                Id = id,
                StartDate = start,
                EndDate = end,
                Subject = subject,
                Details = details,
            });
        }
        #endregion
    }
}
